package com.metro.paperless.common.utils;

import com.metro.core.vo.CommonResult;
import com.metro.core.vo.ResultCode;
import com.metro.paperless.common.beans.constant.PropertiesEnum;
import com.metro.paperless.common.utils.resource.Res;
import com.metro.paperless.sys.beans.vo.SysAttachment;
import com.metro.utils.DateUtil;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <b>负责文件上传下载的类</b><br>
 * 1、uploadImage - 上传单个图片文件<br>
 * 2、uploadImage - 上传多个图片文件（此方法是对:上传单个图片文件方法的补充）<br>
 * 3、uploadAttachment - 上传单个文件<br>
 * 4、uploadAttachment - 上传多个文件（此方法是对：上传单个文件方法的补充）<br>
 * 5、downloadAttachment - 下载单个或多个文件（此方法待定）<br>
 * 6、getFileNameFromUrl - 从给定路径中获得文件名称<br>
 * 7、zoomImage - 将给定图片文件生成缩略图并保存<br>
 * 8、getThumFileName - 根据文件名和尺寸获得缩略图名称<br>
 * 9、createtFileName - 在给定的扩展名（后缀名）前追加特定的日期字符串（格式：yyyyMMddHHmmssSSS）并返回<br>
 * 10、createtFileName - 此方法是createtFileName(String ext)衍生方法，参数默认为jpg<br>
 *
 * @author xk
 */
public class UploadUtil {

    private static Logger log = LoggerFactory.getLogger(UploadUtil.class);

    /**
     * 单个文件上传<br>
     * <p>
     * 系统会配置一个文件上传主目录，不同模块的文件在此目录下分包存放。
     * <p>
     * 如果用户没有指定模块包，则使用系统配置的默认目录。
     * <p>
     * 系统会在该模块下每天建立一个文件夹存放当天上传的文件。
     *
     * @param file MultipartFile对象
     * @param moduleDir 模块名
     * @param request  HttpServletRequest对象
     * @return CommonResult<SysAttachment>对象包含此次上传是否成功
     */
    public static CommonResult<SysAttachment> uploadAttachment(MultipartFile file, String moduleDir, HttpServletRequest request, HttpServletResponse res) {
        CommonResult<SysAttachment> cr = new CommonResult<>();
        // 保存
        try {
            if (file == null || StringUtils.isEmpty(file.getOriginalFilename())) {
                cr.setResult(ResultCode.UPLOAD_FAIL);
                return cr;
            }
            // 根路径
            String rootDir = PropertiesEnum.getPropertyValue(PropertiesEnum.FILE_UPLOAD_ROOT);
            //文件日期
            String day = DateUtil.getCurDate("yyyyMMdd");
            //子路径
            String subDir =  moduleDir + File.separator + day;
            // 获取路径
            String imageDir = rootDir + File.separator + subDir;
            String oldName = file.getOriginalFilename();
            String fileExt = getFileExtension(oldName);
            Long fileId = SequenceUtil.nextValue();
            String newName = fileId + fileExt;
            File tempFile = new File(imageDir, newName);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            file.transferTo(tempFile);
            SysAttachment attachment = new SysAttachment();
            attachment.setId(fileId);
            attachment.setOldName(oldName);
            attachment.setNewName(newName);
            attachment.setPath((subDir+File.separator+newName).replaceAll("\\\\", "/"));
            attachment.setFileType(fileExt);
            cr.setData(attachment);
            cr.setResult(ResultCode.SUCCESS);
            return cr;
        } catch (Exception e) {
            log.error("导入出错", e);
            cr.setResult(ResultCode.UPLOAD_FAIL);
            return cr;
        }
    }


	/**
	 * 单个图片文件上传
	 * 
	 * @param file
	 *            要上传的MultipartFile对象
	 * @param isThumb
	 * @param request
	 * @return 上传后的文件路径（String）
	 */
	public static CommonResult<SysAttachment> uploadImage(
			MultipartFile file, String moduleDir, boolean isThumb,
			HttpServletRequest request,HttpServletResponse res) {
		try {
			// 上传文件
			CommonResult<SysAttachment> cr = uploadAttachment(file,moduleDir,request,res);
			// 如果上传成功在判断是否需要生成缩略图
			if (cr.isSuccess()) {
				/*if (isThumb) {
					String[] thumbs = zoomImage(cr.getData().getPath());
					cr.getData().setThumbPath(thumbs);
				}*/
			}
			return cr;
		} catch (Exception e) {
            log.error("导入失败", e);
			CommonResult<SysAttachment> cr = new CommonResult<>() ;
			cr.setResult(ResultCode.UPLOAD_FAIL);
			return cr;
		}
	}

	/**
	 * 多个图片文件上传
	 * 
	 * @param files
	 *            包含多个MultipartFile对象的数组
	 * @param isThumb
	 * @param request
	 * @return 包含多个CommonResult<UploadImage>对象的集合对象
	 */
	public static CommonResult<List<SysAttachment>> uploadImage(
			MultipartFile[] files, String moduleDir,boolean isThumb,
			HttpServletRequest request,HttpServletResponse res) {
		CommonResult<List<SysAttachment>> cr = new CommonResult<>();
		List<SysAttachment> fileList = new ArrayList<>();
		// 保存
		if (files == null) {
			cr.setResult(ResultCode.UPLOAD_FAIL);
			return cr;
		}
		CommonResult<SysAttachment> uploadRes = null;
		for (MultipartFile multipartFile : files) {
			uploadRes = uploadImage(multipartFile, moduleDir,isThumb, request,res);
			if (uploadRes.isSuccess()) {
				fileList.add(uploadRes.getData());
			}
		}
		return uploadResult(cr, fileList);
	}

	/**
	 * 根据上传文件的数量判断文件上传是否成功，如果有一个文件上传成功了就返回成功
	 * @param cr
	 * @param fileList 上传的文件列表
	 * @return 返回此次上传是否完成
	 */
	private static CommonResult<List<SysAttachment>> uploadResult(CommonResult<List<SysAttachment>> cr , List<SysAttachment> fileList) {
		// 如果有一个文件上传成功了就返回成功
		if (fileList.size() > 0) {
			cr.setData(fileList);
		} else {
			cr.setResult(ResultCode.UPLOAD_FAIL);
		}
		return cr;
	}



	/**
	 * 多个文件上传,只要有一个文件上传成功都认为此次上传是成功的
	 * 
	 * @param files
	 *            MultipartFile数组对象
	 * @param moduleDir
	 *            文件所属模块存放路径
	 * @param request
	 *            HttpServletRequest对象
	 * @return CommonResult<List<SysAttachment>>对象包含此次上传是否成功以及，文件相关的具体数据具体参考
	 *         {@link SysAttachment}
	 */
	public static CommonResult<List<SysAttachment>> uploadAttachment(
			MultipartFile[] files, String moduleDir, HttpServletRequest request,HttpServletResponse res) {
		CommonResult<List<SysAttachment>> cr = new CommonResult<>();
		List<SysAttachment> fileList = new ArrayList<>();
		for (MultipartFile file : files) {
			try {
				CommonResult<SysAttachment> uploadRes = uploadAttachment( file, moduleDir,request,res);
				if (uploadRes.isSuccess()) {
					fileList.add(uploadRes.getData());
				}
			} catch (Exception e) {
                log.error("导入失败", e);
				cr.setResult(ResultCode.UPLOAD_FAIL);
			}
		}
		return uploadResult(cr, fileList);
	}

	/**
	 * 下载单个或多个文件
	 * 
	 * @param id
	 * @param request
	 * @return
	 */
	public static CommonResult<SysAttachment> downloadAttachment(String id,
                                                                       HttpServletRequest request) {
		CommonResult<SysAttachment> cr = new CommonResult<>();
		if (id != null && id.contains(",")) {
			String[] ids = id.split(",");
			for (String _id : ids) {
				// TODO 下载文件
			}
		} else {
			// TODO 下载文件
		}

		return cr;
	}

	/**
	 * 从文件路径中获得文件名称
	 * 
	 * @param s
	 *            文件路径
	 * @return 文件名称
	 */
	public static String getFileNameFromUrl(String s) {
		int i = s.lastIndexOf("\\");
		if (i < 0 || i >= s.length() - 1) {
			i = s.lastIndexOf("/");
			if (i < 0 || i >= s.length() - 1)
				return s;
		}
		return s.substring(i + 1);
	}

	/**
	 * 将给定图片文件生成缩略图并保存
	 * 
	 * @param imagePath
	 *            图片存放路径
	 * @return
	 * @throws NumberFormatException
	 * @throws IOException
	 */
	private static String[] zoomImage(String imagePath)
			throws NumberFormatException, IOException {
		File file = new File(Res.getPropertiy("upload.root.dir")
				+ File.separator + imagePath);
		String fileName = file.getName();
		String fileExt = getFileExtension(fileName);
		String originalPath = file.getParent();
		String thumbFileName = "";// 缩略图文件名
		String thumbPath = originalPath; // 缩略图完整路径
		String thumbs = Res.getPropertiy("upload.thumbs");// 获得配置的缩略图尺寸
		String[] thumbTemp = thumbs.split(",");
		String imageDir = imagePath.substring(0, imagePath.lastIndexOf("/"));
		if (thumbTemp != null) {
			String[] thumbArr = new String[thumbTemp.length];
			Integer maxThumbSize = Integer.parseInt(thumbTemp[0]);
			for (int i = 0; i < thumbTemp.length; i++) {
				thumbFileName = fileName.replace(fileExt, "_" + thumbTemp[i]
						+ fileExt);
				thumbPath = imageDir + "/" + thumbFileName;
				thumbArr[i] = thumbPath;
				// 缩放图片 默认第一个为等比例的
				Thumbnails
						.of(file)
						.sourceRegion(Positions.TOP_LEFT, maxThumbSize,
								maxThumbSize)
						.size(Integer.parseInt(thumbTemp[i]),
								Integer.parseInt(thumbTemp[i]))
						.keepAspectRatio(false).toFile(thumbPath);
			}
			return thumbArr;
		}
		return null;
	}

	/**
	 * 根据File对象获得文件扩展名
	 * 
	 * @param file
	 *            File对象
	 * @return 文件扩展名（String），如：.txt
	 */
	private static String getFileExtension(File file) {
		String fileName = file.getName();
		if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
			return fileName.substring(fileName.lastIndexOf("."));
		} else {
			return "";
		}
	}

	/**
	 * 根据文件名获得文件扩展名
	 * 
	 * @param fileName
	 *            文件名称
	 * @return 文件扩展名（String），如：.txt
	 */
	private static String getFileExtension(String fileName) {
		if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
			return fileName.substring(fileName.lastIndexOf("."));
		} else {
			return "";
		}
	}

	/**
	 * 根据文件名和尺寸获得缩略图名称
	 * 
	 * @param fileName
	 *            文件名称
	 * @param size
	 *            所需要的尺寸（int）
	 * @return 缩略图名称（String）
	 */
	public static String getThumFileName(String fileName, int size) {
		if (fileName != null && fileName.length() > 0) {
			String fileExt = getFileExtension(fileName);
			return fileName.replace(fileExt, "_" + size + fileExt);
		} else {
			return fileName;
		}
	}

}
